/*-
 * Copyright (c) 2010 mod_cfp team <mod-cfp@gmail.com>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * $Id: b00002.c 172 2010-07-13 08:04:49Z mod.cfp $
 */

#include <sys/param.h>
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "mod_cfp.h"

typedef int exm_callback_t(struct cfp_sess *);

struct exm_urls {
	const char	*url;
	exm_callback_t	*callback;
};

struct exm_priv {
	exm_callback_t	*callback;
};

static int	exm_abc(struct cfp_sess *);

struct exm_urls urls[] = {
	{ "/abc",	exm_abc }
};

static void
exm_attach(struct cfp_module *cm)
{

	(void)cm;
}

static void
exm_detach(struct cfp_module *cm)
{

	(void)cm;
}

static int
exm_lookup(struct cfp_sess *sp)
{
#define	N(a)	(sizeof(a) / sizeof((a)[0]))
	struct cfp_txt url;
	struct exm_urls *u;
	int i, len, ret;

	for (i = 0; i < N(urls); i++) {
		u = &urls[i];

		ret = cfp_get_requrl(sp, &url);
		if (ret == -1)
			return (CFP_MATCH_NONE);

		len = MAX(strlen(u->url), CFP_TXT_LEN(&url));
		if (!strncmp(u->url, url.b, len)) {
			sp->arg = u->callback;
			return (CFP_MATCH_OK);
		}
	}
	return (CFP_MATCH_NONE);
#undef N
}

static int
exm_init(struct cfp_sess *sp)
{
	struct exm_priv *ep;

	ep = calloc(1, sizeof(*ep));
	assert(ep != NULL);
	ep->callback = (exm_callback_t *)sp->arg;
	sp->arg = ep;

	return (CFP_RET_DONE);
}

static void
exm_fini(struct cfp_sess *sp)
{
	struct exm_priv *ep = (struct exm_priv *)sp->arg;

	assert(ep != NULL);
	free(ep);
}

static int
exm_start(struct cfp_sess *sp)
{
	struct exm_priv *ep = (struct exm_priv *)sp->arg;
	int ret;

	ret = ep->callback(sp);

	return (ret);
}

static int
exm_abc(struct cfp_sess *sp)
{
	struct cfp_txt method;
	int ret;

	ret = cfp_get_request_method(sp, &method);
	if (ret == -1) {
		cfp_log(sp->module, "Error %d in cfp_get_request_method()",
		    sp->errnum);
		return (CFP_RET_DONE);
	}
	cfp_fprintf(sp, "%.*s", CFP_TXT_LEN(&method), method.b);
	return (CFP_RET_DONE);
}

struct cfp_conf conf = {
	.magic	= CFP_CONF_MAGIC,
	.attach	= exm_attach,
	.detach = exm_detach,
	.lookup = exm_lookup,
	.init = exm_init,
	.fini = exm_fini,
	.start = exm_start,
};
